<?php

# The Inflector transforms words from singular to plural, class names to table names, modularized class names to ones without,
# and class names to foreign keys.

class Inflector {
	
	static function pluralize($word) {
		foreach (self::$pluralRules as $regex => $replace) {
			$matched = preg_match($regex, $word);
			if ($matched) {
				return preg_replace($regex, $replace, $word);
			}
		}
	   return $word;
	}
	
	static function singularize($word) {
		foreach (self::$singularRules as $regex => $replace) {
			$matched = preg_match($regex, $word);
			if ($matched) {
				return preg_replace($regex, $replace, $word);
			}
		}
	   return $word;
	}
	
	static function camelize($word) {
		return preg_replace_callback('/(^|_)(.)/',
			create_function('$matches','return strtoupper($matches[2]);'),
			$word);
	}
	
	static function underscore($word) {
		
		return strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', preg_replace('/([A-Z]+)([A-Z])/', '$1_$2', $word)));
	}
	
	static function humanize($word) {
		return preg_replace('/_/', ' ', self::underscore($word));
	}
	
	static function tableize($className, $camelbackTables = true, $pluralizeTables = true) {
		if ($camelbackTables) $tableName = lcfirst($className);
		else $tableName = self::underscore($className);
		
		if ($pluralizeTables) return self::pluralize($tableName);
		else return $tableName;
	}
	
	static function classify($tableName, $camelbackTables = true, $pluralizeTables = true) {
		if ($camelbackTables) return self::singularize(ucfirst($tableName));
		else return self::camelize(self::singularize($tableName));
	}
	
	static function foreignKey($className, $camelbackFields = true) {
		if ($camelbackFields) return lcfirst($className) . 'Id';
		else return self::underscore($className) . '_id';
	}
	
	
	static private $pluralRules = array(
				'/(fish)$/i' => '$1$2',                 # fish
				'/(x|ch|ss|sh)$/i' => '$1es',            # search, switch, fix, box, process, address
				'/(series)$/i' => '$1$2',
				'/([^aeiouy]|qu)ies$/i' => '$1y',
				'/([^aeiouy]|qu)y$/i' => '$1ies',        # query, ability, agency
				'/(?:([^f])fe|([lr])f)$/i' => '$1$2ves', # half, safe, wife
				'/sis$/i' => 'ses',                       # basis, diagnosis
				'/([ti])um$/i' => '$1a',                 # datum, medium
				'/(p)erson$/i' => '$1$2eople',          # person, salesperson
				'/(m)an$/i' => '$1$2en',                # man, woman, spokesman
				'/(c)hild$/i' => '$1$2hildren',         # child
				'/s$/i' => 's',                           # no change (compatibility)
				'/$/' => 's'
	);
	
	static private $singularRules = array(
				'/(f)ish$/i' => '$1$2ish',
				'/(x|ch|ss|sh)es$/i' => '$1',
				'/(m)ovies$/i' => '$1$2ovie',
				'/(s)eries$/i' => '$1$2eries',
				'/([^aeiouy]|qu)ies$/i' => '$1y',
				'/([lr])ves$/i' => '$1f',
				'/(tive)s$/i' => '$1',
				'/([^f])ves$/i' => '$1fe',
				'/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i' => '$1$2sis',
				'/([ti])a$/i' => '$1um',
				'/(p)eople$/i' => '$1$2erson',
				'/(m)en$/i' => '$1$2an',
				'/(s)tatus$/i' => '$1$2tatus',
				'/(c)hildren$/i' => '$1$2hild',
				'/(n)ews$/i' => '$1$2ews',
				'/s$/i' => ''
	);
	
}

function lcfirst($string) {
	return strtolower($string{0}) . substr($string, 1);
}

?>